#include "login.h"
#include "menu.h"

#include <iostream>

using namespace std;

Menu::Menu(vector<Equipa>& lis_eq, vector<Jogo>& lis_jg, vector<Campeonato>& lis_camp)
{
    lista_equipas = lis_eq;
    lista_jogos = lis_jg;
    lista_campeonatos = lis_camp;

    campeonato_actual = -2;

    pessoa_logged_in.nome = "";
    pessoa_logged_in.nivel = 0;

}

Menu::~Menu() {}

void Menu::menu_principal()
{
    // Verifica se algum utilizador fez login
    if (pessoa_logged_in.nome == "") {
        int resultado = fazer_login();

        // So podemos continuar com o programa se o utilizador tiver feito o login com sucesso (senao saimos automaticamente do programa)
        if (resultado == 0 || resultado == 1) {

            // Verificar se o utilizador ja selecionou algum campeonato
            if (campeonato_actual == -2) {
                cout << "Ainda nao indicou que campeonato pretende aceder" << endl
                     << endl;

                escolher_campeonato();
            }

            bool continuar = true;

            do {
                cout << " __  __                    ____       _            _             _ " << endl
                     << "|  \\/  | ___ _ __  _   _  |  _ \\ _ __(_)_ __   ___(_)_ __   __ _| |" << endl
                     << "| |\\/| |/ _ \\ '_ \\| | | | | |_) | '__| | '_ \\ / __| | '_ \\ / _` | |" << endl
                     << "| |  | |  __/ | | | |_| | |  __/| |  | | | | | (__| | |_) | (_| | |" << endl
                     << "|_|  |_|\\___|_| |_|\\__,_| |_|   |_|  |_|_| |_|\\___|_| .__/ \\__,_|_|" << endl
                     << "                                                    |_|            " << endl
                     << endl;

                cout << "Campeonato actual: Epoca " << lista_campeonatos[campeonato_actual].getAno() << "/" << lista_campeonatos[campeonato_actual].getAno() + 1 << endl;
                if (resultado == 0)
                    cout << "Nome do administrador: " << pessoa_logged_in.nome << endl
                         << endl;
                else
                    cout << "Nome do utilizador: " << pessoa_logged_in.nome << endl
                         << endl;

                cout << "1) Mostrar o nome das equipas todas" << endl
                     << "2) Procurar por uma equipa" << endl
                     << "3) Mostrar os jogos todos" << endl
                     << "4) Escolher um novo campeonato" << endl;

                // So para os administradores
                if (resultado == 0)
                    cout << "5) Adicionar equipa ao campeonato" << endl
                         << "6) Adicionar um jogador a uma equipa" << endl
                         << "7) Criar um campeonato novo" << endl
                         << "8) Adicionar novo jogo ao campeonato" << endl
                         << "9) Adicionar novo utilizador" << endl
                         << "10) Sair" << endl;
                else // Para os utilizadores, a opcao para sair e a 5 e nao a 10
                    cout << "5) Sair" << endl;

                // TODO: Receber o numero como uma string, verificar se essa string e composta so por numeros e depois converter-la usando o atoi
                if (resultado == 0)
                    cout << "Escolha a sua opcao [1-10]: ";
                else
                    cout << "Escolha a sua opcao [1-5]: ";


                int numero;
                cin >> numero;

                switch (numero) {
                case 1:
                    mostrar_equipas();
                    break;
                case 2:
                    procurar_equipa();
                    break;
                case 3:
                    mostrar_jogos_todos();
                    break;
                case 4:
                    escolher_campeonato();
                    break;

                    // As opcoes daqui para a frente so estao disponiveis para os administradores
                case 5:
                    if (resultado == 0)
                        adicionar_equipa_campeonato();
                    else {
                        continuar = false;
                        cout << "Cuidado com os zombies :)" << endl;
                    }

                    break;
                case 6:
                    if (resultado == 0)
                        adicionar_jogador_equipa();
                    else {
                        cout << "OPCAO NAO EXISTE" << endl;

                        string temp;
                        cin >> temp;
                    }

                    break;
                case 7:
                    if (resultado == 0)
                        criar_novo_campeonato();
                    else {
                        cout << "OPCAO NAO EXISTE" << endl;

                        string temp;
                        cin >> temp;
                    }

                    break;
                case 8:
                    if (resultado == 0)
                        adicionar_jogo_campeonato();
                    else {
                        cout << "OPCAO NAO EXISTE" << endl;
                        string temp;
                        cin >> temp;
                    }

                    break;
                case 9:
                    if (resultado == 0)
                        adicionar_novo_utilizador();
                    else {
                        cout << "OPCAO NAO EXISTE" << endl;

                        string temp;
                        cin >> temp;
                    }

                    break;

                case 10:
                    if (resultado == 0) {

                        continuar = false;
                        cout << "Cuidado com os zombies :)" << endl;
                        /*                ASCII ZOMBIE
                                             .....
                                            C C  /
                                           /<   /
                            ___ __________/_#__=o
                           /(- /(\_\________   \
                           \ ) \ )_      \o     \
                           /|\ /|\       |'     |
                                         |     _|
                                         /o   __\
                                        / '     |
                                       / /      |
                                      /_/\______|
                                     (   _(    <
                                      \    \    \
                                       \    \    |
                                        \____\____\
                                        ____\_\__\_\
                                      /`   /`     o\
                                      |___ |_______|.. . b'ger
                        */
                    }
                    else {
                        cout << "OPCAO NAO EXISTE" << endl;

                        string temp;
                        cin >> temp;
                    }

                    break;
                default:
                    cout << "OPCAO NAO EXISTE" << endl;

                    string temp;
                    cin >> temp;
                    break;
                }
            } while (continuar == true);
        }
    }
}

void Menu::mostrar_equipas()
{
    vector<Equipa> vect = lista_campeonatos[campeonato_actual].getEquipas();

    for (vector<Equipa>::iterator k = vect.begin(); k != vect.end(); k++) {
        cout << k->getNomeEquipa() << endl;
    }
    esperar_input();
}

void Menu::procurar_equipa()
{
    cout << endl
         << endl
         << "Indique o nome da equipa que quer procurar: ";

    string equipa;
    cin >> equipa;


    // Vector de equipas do campeonato actual
    vector<Equipa> equipas_no_campeonato = lista_campeonatos[campeonato_actual].getEquipas();

    // Se no final do proximo ciclo isto estiver a false, entao nao se encontrou a equipa
    bool encontrou_equipa = false;

    for (vector<Equipa>::iterator k = equipas_no_campeonato.begin(); k != equipas_no_campeonato.end(); k++) {
        if (k->getNomeEquipa() == equipa) {
            cout << "Jogadores que pertencem a equipa: " << k->getNomeEquipa() << endl;
            k->imprimir();

            cout << "Deseja ver uma lista de jogos desta equipa? (S/N) " << endl;
            string escolha;
            cin >> escolha;

            if (escolha == "S" or escolha == "s") {
                int counter = 1;

                for (vector<Jogo>::size_type i = 0; i != lista_jogos.size(); i++) {
                    Equipa* eq1 = lista_jogos[i].getEquipa1();
                    Equipa* eq2 = lista_jogos[i].getEquipa2();

                    if (eq1->getNomeEquipa() == equipa or eq2->getNomeEquipa() == equipa) {
                        cout << "---- Jogo " << counter << " ----" << endl;
                        lista_jogos[i].imprimir();
                        cout << "----------------" << endl
                             << endl;
                        counter++;
                    }
                }
            }
            encontrou_equipa = true;
        }
    }

    if (encontrou_equipa == false) {
        cout << "Nao foi encontrada nenhuma equipa com o nome \"" << equipa << "\"." << endl;
    }

    esperar_input();
}

void Menu::mostrar_jogos_todos()
{
    int counter = 0;

    cout << endl
         << endl;

    // Jogos que estao no campeonato actual
    vector<Jogo*> jogos_no_campeonato = lista_campeonatos[campeonato_actual].getJogos();

    for (vector<Jogo*>::size_type k = 0; k != jogos_no_campeonato.size(); k++) {
        // Os indices dos jogos comecam a partir do 1
        counter++;

        Equipa* eq1 = jogos_no_campeonato[k]->getEquipa1();
        Equipa* eq2 = jogos_no_campeonato[k]->getEquipa2();

        cout << counter << ") " << eq1->getNomeEquipa() << " contra " << eq2->getNomeEquipa() << endl;
    }

    // TODO: Arranjar uma forma de implementar isto
    // cout << "Deseja ver mais informacao sobre um jogo em particular? (digite q para sair ou [1-" << counter << "] para ver a informacao sobre esse jogo: ";

    cout << "Deseja ver mais informacao sobre um jogo em particular? (use 0 para sair) [0-" << counter << "]: ";

    int escolha;
    cin >> escolha;

    // TODO: se a escolha for maior que o counter, lancar um erro
    if (escolha > 0) {
        if (escolha <= counter) {
            escolha -= 1; // converter o input num indice do vector

            cout << endl
                 << "----------------" << endl;

            jogos_no_campeonato[escolha]->imprimir();
            cout << "----------------" << endl
                 << endl;
        }
        else {
            cout << "O jogo indicado nao existe na base de dados" << endl
                 << endl;

        }
    }

    esperar_input();
}


/*
 * Codigos de erro possiveis:
 *  0 - Utilizador fez login com o nivel de administador
 *  1 - Utilizador fez login com o nivel de utilizador (nao implementado - Rolando 19:47 23/12/2009)
 *  2 - Utilizador desistiu de fazer o login (programa deve de sair para a shell)
 *  3 - Utilizador excedeu o numero de tentativas que tinha para fazer o login
 */
int Menu::fazer_login()
{
    cout << "  Menu de login" << endl
         << endl;

    bool continuar = false;

    // Utilizador so tem 5 tentativas para fazer o login
    int tentativas = 5;

    while (!continuar) {
        cout << "Nome do utilizador (escreva 0 para desistir) (tentativas restantes " << tentativas << "): ";
        string nome;
        cin >> nome;            // TODO: Usar getline

        if (nome == "0")
            return 2;

        cout << "Password do utilizador: ";
        string password;
        cin >> password;        // TODO: Usar getline

        int login_feito = log_manager.efectuar_login(nome, password);

        if (login_feito == 0) {
            cout << "Bem vindo administrador " << nome << "." << endl;
            continuar = true;
            pessoa_logged_in.nome = nome;
            pessoa_logged_in.nivel = 0;
        }
        else if (login_feito == 1) {
            cout << "Bem vindo utilizador " << nome << "." << endl;
            continuar = true;
            pessoa_logged_in.nome = nome;
            pessoa_logged_in.nivel = 1;
        }
        else {
            cout << "Username e password errados." << endl;
            cout << endl
                 << endl;

            // Actualizar tentativas
            tentativas--;

            if (tentativas == 0) {
                cout << "Numero de tentativas excedidas o programa vai desligar." << endl;

                return 3;
            }

            else
                cout << "Por fazer tente outra vez." << endl;
        }
    }

    if (pessoa_logged_in.nivel == 0)
        return 0;
    else if (pessoa_logged_in.nivel == 1)
        return 1;

    // Universo acabou de ser destruido. Arrumar as coisas e ir embora
    return -1;

}


bool Menu::e_numero(string num)
{
    // Devolve true se a string "s" e constituida exclusivamente por numeros
    for (string::size_type k = 0; k != num.size(); k++)
    {
        if (!isdigit(num[k]))
            return false; // Existe um caracter que nao e um numero
    }
    return true;
}

// TODO: Devia de haver uma opcao para poder selecionar todos os campeonatos
void Menu::escolher_campeonato()
{
    bool continuar = false;

    do {

        cout << " Lista de campeonatos" << endl;

        for (vector<Campeonato>::size_type k = 0; k != lista_campeonatos.size(); k++) {
            cout << k+1 << ") Epoca " << lista_campeonatos[k].getAno() << "/" << lista_campeonatos[k].getAno() + 1 <<  endl;
        }

        cout << "Indique o numero do campeonato a que pretende aceder [1-" << lista_campeonatos.size() << "]: ";

        vector<Campeonato>::size_type escolha;
        cin >> escolha;

        escolha -= 1;

        if (escolha >= lista_campeonatos.size() || escolha < 0)
            cout << "Opcao nao e valida." << endl;
        else {
            campeonato_actual = escolha;
            continuar = true;
        }
    } while (!continuar);
}

void Menu::adicionar_equipa_campeonato()
{
    cout << " Adicionar uma equipa ao campeonato da epoca "
         << lista_campeonatos[campeonato_actual].getAno() << "/"
         << lista_campeonatos[campeonato_actual].getAno() + 1 << endl
         << endl;

    cout << "Nome da equipa (escreva 0 para sair): ";
    string nome;
    cin >> nome;

    if (nome != "0") {

        cout << "Nome do treinador (escreva 0 para sair): ";
        string treinador;
        cin >> treinador;

        if (treinador != "0") {

            Equipa temp_equipa(treinador, nome);

            lista_equipas.push_back(temp_equipa);

            for (vector<Equipa>::size_type k = 0; k != lista_equipas.size(); k++) {
                if (lista_equipas[k] == temp_equipa) {
                    try {
                        lista_campeonatos[campeonato_actual].adicionarEquipa(&lista_equipas[k]);
                    }
                    catch (CampeonatoCheio) {
                        cout << "Nao foi possivel adicionar a equipa porque o campeonato ja esta cheio." << endl;
                    }

                    break;
                }
            }
        }
    }
}

void Menu::adicionar_jogador_equipa()
{
    cout << " Adicionar um jogador a uma equipa que esta a participar neste campeonato"
         << endl;

    bool continuar = false;

    // Vector que contem as equipas que estao a participar no campeonato actual
    vector<Equipa> equipas_no_campeonato = lista_campeonatos[campeonato_actual].getEquipas();
    Equipa* ptr_eq = NULL; // Equipa a quem vai ser adicionada o jogador

    do {
        cout << "Nome da equipa a adicionar um jogador (escreva 0 para sair): ";
        string nome;
        cin >> nome;

        if (nome == "0")
            continuar = true;   // Sair do ciclo e da funcao
        else {
            bool encontrou_equipa = false;

            for (vector<Equipa>::size_type k = 0; k != equipas_no_campeonato.size(); k++) {
                if (equipas_no_campeonato[k].getNomeEquipa() == nome) {
                    encontrou_equipa = true;

                    vector<Equipa*> teste = lista_campeonatos[campeonato_actual].getEquipas2();

                    cout << "Nome do jogador: ";
                    string nome;
                    cin >> nome;

                    cout << "Idade do jogador: ";
                    int idade;
                    cin >> idade;

                    Jogador temp_jogador(nome.c_str(), idade);

                    for (vector<Equipa*>::size_type j = 0; j != teste.size(); j++) {
                        if (teste[j]->getNomeEquipa() == equipas_no_campeonato[k].getNomeEquipa()) {
                            Equipa* teste2 = teste[j];

                            teste2->adicionarJogador(temp_jogador);
                        }
                    }

                }
            }

            if (!encontrou_equipa) {
                cout << "Equipa nao existe neste campeonato." << endl;
            }
            else {
                continuar = true;
            }
        }
    } while (!continuar);

    // cout << "Nome do jogador: ";
    // string nome;
    // cin >> nome;

    // cout << "Idade do jogador: ";
    // int idade;
    // cin >> idade;

    // Jogador temp_jogador(nome, idade);

    //ptr_eq->adicionarJogador(temp_jogador);
    // cout << endl
    //      << endl
    //      << "----" << endl
    //      << ptr_eq->getPlantel()[0].getNome() << endl
    //      << endl;

}

void Menu::criar_novo_campeonato()
{
    cout << " Criar um novo campeonato vazio" << endl
         << endl;

    bool continuar = false;
    do {

        cout << "Ano de inicio da epoca (escrever 0 para sair): ";
        int ano;
        cin >> ano;

        if (ano == 0) {
            cout << "Hockey em patins na epoca de Jesus Cristo e que era bom :)" << endl
                 << endl;
            continuar = true;

            esperar_input();
        }

        bool encontrou_campeonato = false;
        for (vector<Campeonato>::iterator k = lista_campeonatos.begin(); k != lista_campeonatos.end(); k++) {
            if (k->getAno() == ano)
                encontrou_campeonato = true;
        }

        if (encontrou_campeonato) {
            cout << "Ja existe um campeonato para esse ano." << endl
                 << endl;
            encontrou_campeonato = false;
        }
        else {
            Campeonato camp_adicionar(ano);

            lista_campeonatos.push_back(camp_adicionar);

            continuar = true;
        }
    } while (!continuar);
}

void Menu::adicionar_jogo_campeonato()
{
    cout << " Adicionar um novo jogo ao campeonato da epoca "
         << lista_campeonatos[campeonato_actual].getAno() << "/"
         << lista_campeonatos[campeonato_actual].getAno() + 1 << endl
         << endl;

    // Vector que contem as equipas que estao a participar no campeonato actual
    vector<Equipa> equipas_no_campeonato = lista_campeonatos[campeonato_actual].getEquipas();

    // Se for true, permite sair da funcao sem executar o resto dela
    bool sair_da_funcao = false;

    bool continuar = false;
    // Obter a equipa que esta a jogar em casa
    Equipa* ptr_eq1 = NULL;
    do {
        // TODO: Fazer o sistema para sair disto
        cout << "Nome da equipa que jogou em casa (escreva 0 para sair): ";

        string nome_eq1;
        cin >> nome_eq1;

        if (nome_eq1 == "0") {
            continuar = true;
            sair_da_funcao = true;
            break; // Sair do ciclo
        }

        // Verificar se a equipa existe
        bool encontrou_equipa = false;

        for (vector<Equipa>::iterator k = equipas_no_campeonato.begin(); k != equipas_no_campeonato.end(); k++) {
            if (k->getNomeEquipa() == nome_eq1) {
                encontrou_equipa = true;
                ptr_eq1 = &(*k);
                // TODO: Verificar se a equipa tem os jogadores minimos para jogar (pode ter sido criada no menu e ainda nao ter sido adicionado jogadores a ela)
            }
        }
        if (!encontrou_equipa)
            cout << "Equipa nao existe neste campeonato." << endl
                 << endl;
        else
            continuar = true;

    } while (!continuar);

    if (!sair_da_funcao) {

        // Obter a equipa que esta a jogar fora
        Equipa* ptr_eq2 = NULL;

        continuar = false;
        do {
            // TODO: Fazer o sistema para sair disto

            cout << "Nome da equipa que jogou fora (escreva 0 para sair): ";

            string nome_eq2;
            cin >> nome_eq2;

            if (nome_eq2 == "0") {
                continuar = true;
                sair_da_funcao = true;
                break;
            }

            // Primeiro temos de verificar se a equipa1 e diferente da equipa2
            if (ptr_eq1->getNomeEquipa() == nome_eq2) {
                cout << "A equipa de fora nao pode ter o mesmo nome que a equipa que esta a jogar em casa." << endl;
                continue;
            }

            // Verificar se a equipa existe
            bool encontrou_equipa = false;

            for (vector<Equipa>::iterator k = equipas_no_campeonato.begin(); k != equipas_no_campeonato.end(); k++) {
                if (k->getNomeEquipa() == nome_eq2) {
                    encontrou_equipa = true;
                    ptr_eq2 = &(*k);
                }
            }

            if (!encontrou_equipa)
                cout << "Equipa nao existe neste campeonato." << endl
                     << endl;
            else
                continuar = true;

        } while (!continuar);

        if (!sair_da_funcao) {

            cout << "Local onde foi feito o jogo: ";
            string local;
            cin >> local;

            cout << "Nome do arbitro: ";
            string arbitro;
            cin >> arbitro;

            continuar = false;
            int mes = 0;
            do {
                cout << "Mes a que foi realizado o jogo [1-12]: ";
                cin >> mes;

                if (mes < 1 || mes > 12)
                    cout << "Mes nao valido" << endl
                         << endl;
                else
                    continuar = true;

            } while (!continuar);

            continuar = false;
            int dia;
            do {
                cout << "Dia a que foi realizado o jogo [1-31]: ";
                cin >> dia;

                if (dia < 1 || dia > 31)
                    cout << "Dia nao e valido" << endl
                         << endl;
                else
                    continuar = true;

            } while (!continuar);

            cout << "Qual foi o resultado da equipa " << ptr_eq1->getNomeEquipa() << ": ";
            int resultado_eq1;
            cin >> resultado_eq1;

            cout << "Qual foi o resultado da equipa " << ptr_eq2->getNomeEquipa() << ": ";
            int resultado_eq2;
            cin >> resultado_eq2;

            // Criar o jogo que vai ser adicionado ao vector lista_jogos
            Jogo jogo_adicionar(local, arbitro, dia, mes, ptr_eq1, ptr_eq2, resultado_eq1, resultado_eq2);

            lista_jogos.push_back(jogo_adicionar);
            lista_campeonatos[campeonato_actual].adicionarJogo(&(*(lista_jogos.rbegin())));

            cout << "Jogo entre as equipas " << ptr_eq1->getNomeEquipa()
                 << " e " << ptr_eq2->getNomeEquipa() << " foi adicionado com sucesso a epoca "
                 << lista_campeonatos[campeonato_actual].getAno() << "/" << lista_campeonatos[campeonato_actual].getAno() + 1 << endl
                 << endl;
        }
    }
}

void Menu::adicionar_novo_utilizador()
{
    cout << " Adicionar um novo utilizador a base de dados" << endl
         << endl;

    cout << "Nome (escreva 0 para sair): ";

    string nome;
    cin >> nome;

    if (nome != "0") {

        cout << "Password: ";

        string password;
        cin >> password;

        int nivel = -1;
        bool continuar = false;
        do {

            cout << "Nivel [0 para administrador, 1 para utilizador]: ";

            cin >> nivel;

            if (nivel != 0 && nivel != 1)
                cout << "Opcao nao valida." << endl
                     << endl;

            else
                continuar = true;
        } while (!continuar);

        bool resultado = log_manager.adicionar_novo_login(nome, password, nivel);

        if (resultado) {
            cout << "Login adicionado com sucesso" << endl
                 << endl;
        }
        else {
            cout << "Ja existe um utilizador com esse nome." << endl;
        }

        esperar_input();
    }
}

void Menu::esperar_input()
{
    cout << "Pressione uma tecla para continuar" << endl;

    string temp;
    cin >> temp;
}
